/**
* \file DGVVolumePlotVTK.h
*
* \brief This file defines a class for display Volume Plots using VTK.
* \author Shekhar S. Chandra, 2008-2009
*
* This file is part of DGV Library.
*
* DGV is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* DGV is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with DGV.  If not, see <http://www.gnu.org/licenses/>.
*/
#ifndef DGVVOLUMEPLOTVTK_H
#define DGVVOLUMEPLOTVTK_H

#include <QtGui/QtGui>

#include "QVTKWidget.h"
#include "vtkSmartPointer.h"
#include "vtkAlgorithmOutput.h"
#include "vtkPiecewiseFunction.h"
#include "vtkColorTransferFunction.h"
#include "vtkVolumeProperty.h"
#include "vtkFixedPointVolumeRayCastMapper.h"
#include "vtkVolumeRayCastMapper.h"
#include "vtkVolumeRayCastCompositeFunction.h"
#include "vtkVolume.h"
#include "vtkCubeAxesActor2D.h" //For axes
#include "vtkRenderer.h"
#include "vtkRenderWindow.h"

#include "DGVAliases.h"
#include "DGVBlitzArrayCasterVTK.h"
#include "DGVSurfacePlotVTK.h"

typedef vtkSmartPointer<vtkImageData> PlotData; //!< Smart Pointers for Automated Garbage Collection
typedef vtkSmartPointer<vtkAlgorithmOutput> PlotAlgorithmOutput; //!< Smart Pointers for Automated Garbage Collection
typedef vtkSmartPointer<vtkPiecewiseFunction> PlotPiecewiseFunction; //!< Smart Pointers for Automated Garbage Collection
typedef vtkSmartPointer<vtkColorTransferFunction> PlotColorTransferFunction; //!< Smart Pointers for Automated Garbage Collection
typedef vtkSmartPointer<vtkVolumeProperty> PlotVolumeProperty; //!< Smart Pointers for Automated Garbage Collection
typedef vtkSmartPointer<vtkFixedPointVolumeRayCastMapper> PlotFixedRayCastMapper; //!< Smart Pointers for Automated Garbage Collection
typedef vtkSmartPointer<vtkVolumeRayCastMapper> PlotRayCastMapper; //!< Smart Pointers for Automated Garbage Collection
typedef vtkSmartPointer<vtkVolumeRayCastCompositeFunction> PlotCompositeFunction; //!< Smart Pointers for Automated Garbage Collection
typedef vtkSmartPointer<vtkVolume> PlotVolume; //!< Smart Pointers for Automated Garbage Collection
typedef vtkSmartPointer<vtkCubeAxesActor2D> PlotAxes; //!< Smart Pointers for Automated Garbage Collection
typedef vtkSmartPointer<vtkRenderer> PlotRenderer; //!< Smart Pointers for Automated Garbage Collection
typedef vtkSmartPointer<vtkRenderWindow> PlotRenderWindow; //!< Smart Pointers for Automated Garbage Collection

/*!
    \class DGVVolumePlotVTK
    \brief This class represents the DGV Volume Plot Display object using VTK.
    \author Shekhar S. Chandra, 2008-2009

    The class displays image values using OpenGL via the VTK library. The rendering is encapsulated within
    a QVTK widget.
    Controls:
        - Left Mouse (hold): rotate plot.
        - Wheel: zoom the camera.
        - Middle Mouse (hold): translate plot.
        - Right Mouse: context menu and zoom toggle.
        - Keypress f: fly to the picked point.
        - Keypress Shift+r: reset the camera view along the current view direction.
        - Keypress r: reset the zoom to defaults.

    Usage Example:
    \code
    volViewer = new DGVVolumePlotVTK;

    //Load or create 3D data called imageData
    ...

    volViewer->setName(name);
    volViewer->setData(imageData); //imageData can be a vtkImageData object or a 3D Blitz Array
    volViewer->generatePlot();
    volViewer->generateAxes();
    volViewer->show();
    \endcode
*/
class DGV_VTK_EXPORT DGVVolumePlotVTK : public QVTKWidget
{
    Q_OBJECT

public:
    /*!
        \fn DGVVolumePlotVTK::DGVVolumePlotVTK(QWidget *parent = 0)
        \brief The standard constructor
    */
    DGVVolumePlotVTK(QWidget *parent = 0);
    /*!
        \fn DGVVolumePlotVTK::~DGVVolumePlotVTK()
        \brief The standard destructor
    */
    virtual ~DGVVolumePlotVTK();

    /*!
        \fn DGVVolumePlotVTK::setName(QString filename)
        \brief Set the name of the plot.
    */
    void setName(QString filename);
    /*!
        \fn DGVVolumePlotVTK::setData(Array<imageType,3> &data)
        \brief Set the data to be plotted.
    */
    void setData(Array<imageType,3> &data);
    /*!
        \fn DGVVolumePlotVTK::setData(Array<complex<imageType>,3> &data)
        \brief Set the complex data to be plotted. Volume display will show absolute magnitude, real and imaginary (3 scalar components).

        Internal array only holds absolute magnitude.
    */
    void setData(Array<complex<imageType>,3> &data);
    /*!
        \fn DGVVolumePlotVTK::setData(vtkImageData *data)
        \brief Set the data to be plotted.
    */
    void setData(vtkImageData *data);
    /*!
        \fn DGVVolumePlotVTK::SetInputConnection(vtkAlgorithmOutput *data)
        \brief Set the data to be plotted.
    */
    void SetInputConnection(vtkAlgorithmOutput *data);

    /*!
        \fn DGVVolumePlotVTK::generatePlot()
        \brief Generates a volume plot from the data provided.
    */
    void generatePlot();
    /*!
        \fn DGVVolumePlotVTK::generateAxes()
        \brief Generates and enables the axes on the plot.
    */
    void generateAxes();

    /*!
        \fn DGVVolumePlotVTK::unsignedCharModeOn()
        \brief Volume plot will expect unsigned chars in image data type.
        WARNING: Plotting appears not to work in unsigned char mode.
    */
    inline void unsignedCharModeOn()
    {   unsignedCharMode = true;    }
    /*!
        \fn DGVVolumePlotVTK::unsignedCharModeOff()
        \brief Volume plot will expect any image data type.
    */
    inline void unsignedCharModeOff()
    {   unsignedCharMode = false;   }
    /*!
        \fn DGVVolumePlotVTK::setXLabel(QString text)
        \brief Set the label of x-axis.
    */
    void setXLabel(QString text);
    /*!
        \fn DGVVolumePlotVTK::setYLabel(QString text)
        \brief Set the label of y-axis.
    */
    void setYLabel(QString text);
    /*!
        \fn DGVVolumePlotVTK::setZLabel(QString text)
        \brief Set the label of z-axis.
    */
    void setZLabel(QString text);
    /*!
        \fn DGVVolumePlotVTK::setBackground(double r, double g, double b)
        \brief Sets the background of the renderer to colour (r,g,b).
    */
    void setBackground(double r, double g, double b);
    /*!
        \fn DGVVolumePlotVTK::setAxesAsClosestTriad()
        \brief Set the axes display method as the closest triad to viewer
    */
    void setAxesAsClosestTriad();
    /*!
        \fn DGVVolumePlotVTK::setAxesAsClosestTriad()
        \brief Set the axes display method as the outer edges from the viewer
    */
    void setAxesAsOuterEdges();

    /*!
        \fn DGVVolumePlotVTK::saveVTI(const QString filename)
        \brief Saves data using VTK XML Image (VTI) format with stored filename.
    */
	bool saveVTI(const QString filename);
	/*!
        \fn DGVVolumePlotVTK::saveVTK(const QString filename)
        \brief Saves data using VTK Legacy Structured Points (VTK) format with stored filename.
    */
	bool saveVTK(const QString filename);

    /*!
        \fn DGVVolumePlotVTK::strippedName()
        \brief Returns the stripped (path removed) name of the plot.
    */
    QString strippedName();
    /*!
        \fn DGVVolumePlotVTK::strippedNamePrefix()
        \brief Returns the stripped (path removed) name of the plot with "VPlot" prefix.
    */
    QString strippedNamePrefix();
    /*!
        \fn DGVVolumePlotVTK::data()
        \brief Returns the data in Blitz array form.
    */
    inline Array<imageType,3>& data()
    {   return plotArray;   }

public slots:
    /*!
        \fn DGVVolumePlotVTK::scanVolume()
        \brief Scan through x-y plane using surface plots.
    */
    void scanVolume();
    /*!
        \fn DGVVolumePlotVTK::xLabel()
        \brief Ask for x-label
    */
    void xLabel();
    /*!
        \fn DGVVolumePlotVTK::yLabel()
        \brief Ask for y-label
    */
    void yLabel();
    /*!
        \fn DGVVolumePlotVTK::zLabel()
        \brief Ask for z-label
    */
    void zLabel();
    /*!
        \fn DGVVolumePlotVTK::opacity()
        \brief Ask for opacity level
    */
    void opacity();
    /*!
        \fn DGVVolumePlotVTK::background()
        \brief Ask for rgb values and change background to that colour.
    */
    void background();
    /*!
        \fn DGVVolumePlotVTK::axesProperties()
        \brief Ask for rgb values and change axes to that colour.
    */
    void axesProperties();
    /*!
        \fn DGVVolumePlotVTK::toggleAxesAsClosestTriad()
        \brief Toggles if the axes are display with closest triad display mode.
    */
    void toggleAxesAsClosestTriad();
    /*!
        \fn DGVVolumePlotVTK::toggleAntiAliasing()
        \brief Toggles the Anti-Aliasing in display. May slow rendering if enabled.
    */
    void toggleAntiAliasing();
    /*!
        \fn DGVVolumePlotVTK::save()
        \brief Saves the data.
    */
    void save();
    /*!
        \fn DGVVolumePlotVTK::renameData()
        \brief Renames the volume data.
    */
    void renameData();

signals:
    /*!
        \fn DGVTableVTK::surfacePlotAvailable(DGVSurfacePlotVTK *)
        \brief Send signal that a surface plot/animation is available for showing.
    */
    void surfacePlotAvailable(DGVSurfacePlotVTK *);
    /*!
        \fn DGVPlot::nameChanged(const QString newName)
        \brief Send signal that the window has been renamed.
    */
    void nameChanged(const QString newName);

protected:
    bool loaded; //!< Data loaded?
    bool externalData; //!< External Data used?
    bool mapper; //!< Has mapper been setup?
    bool generated; //!< Plot has been generated?
    bool axisGenerated; //!< Axis has been generated?
    bool closestTriad; //!< Closest Triad being displayed?
    bool antiAliasing; //!< Smooth Polygons?
    bool imageDataSource; //!< Source is VTK ImageData?
    QString name; //!< Name of the plot

    bool unsignedCharMode; //!< Use this mode?

    ///Context Menu
	QMenu *contextMenu; //!< Context Menu
	QAction *surfaceAct; //!< Action object for surface scan.
	//------------------
	QAction *xLabelAct; //!< Show Change x label
	QAction *yLabelAct; //!< Show Change y label
	QAction *zLabelAct; //!< Show Change z label
	QAction *opacityAct; //!< Change opacity
	QAction *backgroundAct; //!< Change background colour?
	QAction *axesAct; //!< Change axes colour?
	QAction *triadAct; //!< Change Axis Type
	QAction *antiAliasingAct; //!< Change Anti Aliasing
    //------------------
    QAction *saveAct; //!< Saves data as VTI file
    QAction *renameAct; //!< Refreshes window
	QAction *closeAct; //!< Closes window

    PlotData plotData; //!< Actual data stored as using an image geometry
    DGVBlitzArrayCasterVTK<imageType> Blitz; //!< For casting Blitz arrays to and from VTK structures
    Array<imageType,3> plotArray; //!< Plot data in array form.

    PlotAlgorithmOutput inputConnection; //!< VTK connection member.

    ///VTK Volume instances
    PlotPiecewiseFunction opacityTransferFunction; //!< Control Transparency
    PlotColorTransferFunction colorTransferFunction; //!< Colour map
    PlotVolumeProperty volumeProperty; //!< Encapsulates transparency and colour

    PlotFixedRayCastMapper volumeMapper_Fixed; //!< Maps data to grid volume
    PlotRayCastMapper volumeMapper; //!< Maps data to grid volume with unsigned chars
    PlotCompositeFunction compositeFunction;

    PlotVolume volume; //!< Actual volume actor
    PlotAxes axes; //!< Axis for plot

    PlotRenderer renderer; //!< Renderer of the plot
    PlotRenderWindow renderWin; //!< Window that controls the renderer

    /*!
		\fn DGVVolumePlotVTK::setupEvents()
		\brief Executes common events setup code.
	*/
	void setupEvents();
	/*!
		\fn DGVVolumePlotVTK::contextMenuEvent(QContextMenuEvent *event)
		\brief The context menu setup member
	*/
	void contextMenuEvent(QContextMenuEvent *event);
};

#endif // DGVVOLUMEPLOTVTK_H
